<!--
 * Copyright © 2022 XXXXXXXXX
 * @Author: zhangxiang
 * @Date: 2022-08-04 18:01:36
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-09-21 15:02:32
 * @Description:
 *
-->

<template>
  <div class="node-mgmt-ctn">
    <el-row type="flex" style="margin-bottom: 20px">
      <el-input
        v-model="searchKey"
        style="width: 200px; margin-right: 20px"
        size="small"
        class="input"
        placeholder="请输入关键字进行过滤"
        clearable
        @clear="clearClick"
        @keyup.enter.native="queryClick"
      />
      <el-button
        size="small"
        type="primary"
        @click="queryClick"
      >查询</el-button>
      <!-- <el-button
        size="small"
        type="primary"
        style="margin-left: auto"
        icon="el-icon-plus"
        @click="addNodeClick"
      >添加节点</el-button> -->
    </el-row>
    <el-table
      key="node"
      v-loading="loading"
      class="node-table table-fixed"
      :data="list"
      header-cell-class-name="listHeaderCell"
      :header-cell-style="{ background: '#F3F3F3', color: '#696969' }"
      border
    >
      <el-table-column
        prop="cloudVendor"
        label="云商名称"
        min-width="110"
        show-overflow-tooltip=""
      >
        <template slot-scope="scope">
          {{ cloudVendorToChn(scope.row.cloudVendor) }}
        </template>
      </el-table-column>
      <el-table-column
        prop="k8sClusterName"
        label="集群名称"
        min-width="180"
        show-overflow-tooltip=""
      />
      <el-table-column
        prop="nodeName"
        label="节点名称"
        min-width="165"
        show-overflow-tooltip=""
      />
      <el-table-column prop="nodeHardware" label="节点类型" width="90" />
      <el-table-column prop="nodeRole" label="角色" width="90" />
      <el-table-column prop="status" label="状态" width="90" />
      <el-table-column prop="framework" label="架构" width="80" />
      <el-table-column prop="nodeIp" label="IP" width="130" />
      <el-table-column
        prop="nodeContainerQuota"
        label="容器组（已使用/分配额度）"
        width="100"
        show-overflow-tooltip=""
      >
        <template slot="header">
          <span>容器组</span>
          <el-tooltip
            class="item"
            effect="dark"
            content="已使用 / 分配额度"
            placement="top"
          >
            <i class="el-icon-info" style="margin-left: 3px"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          {{ scope.row.nodeContainerUseNum }}/{{ scope.row.nodeContainerQuota }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeCpuQuota"
        label="CPU(Cores)（已使用/分配额度）"
        width="140"
      >
        <template slot="header">
          <span>CPU（Cores）</span>
          <el-tooltip
            class="item"
            effect="dark"
            content="已使用 / 分配额度"
            placement="top"
          >
            <i class="el-icon-info" style="margin-left: 3px"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          {{ scope.row.nodeCpuUseNum }}/{{ scope.row.nodeCpuQuota }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeMemQuota"
        label="内存(GiB)（已使用/分配额度）"
        width="120"
      >
        <template slot="header">
          <span>内存（GiB）</span>
          <el-tooltip
            class="item"
            effect="dark"
            content="已使用 / 分配额度"
            placement="top"
          >
            <i class="el-icon-info" style="margin-left: 3px"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          {{ scope.row.nodeMemUseNum }}/{{ scope.row.nodeMemQuota }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeSysDiskQuota"
        label="系统盘(GiB)（已使用/总额度）"
        width="140"
      >
        <template slot="header">
          <span>系统盘（GiB）</span>
          <el-tooltip
            class="item"
            effect="dark"
            content="已使用 / 总额度"
            placement="top"
          >
            <i class="el-icon-info" style="margin-left: 3px"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          {{ scope.row.nodeSysDiskUseNum }}/{{ scope.row.nodeSysDiskQuota }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeDiskQuota"
        label="磁盘(GiB)（已使用/总额度）"
        width="120"
      >
        <template slot="header">
          <span>磁盘（GiB）</span>
          <el-tooltip
            class="item"
            effect="dark"
            content="已使用 / 总额度"
            placement="top"
          >
            <i class="el-icon-info" style="margin-left: 3px"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          {{ scope.row.nodeDiskUseNum }}/{{ scope.row.nodeDiskQuota }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeGpuSpec"
        label="GPU显卡型号和个数"
        min-width="160"
        show-overflow-tooltip=""
      >
        <template slot-scope="scope">
          {{ scope.row.nodeGpuSpec || '-' }}
        </template>
      </el-table-column>
      <el-table-column
        prop="nodeGpuMemStr"
        label="GPU显存(GiB)"
        width="120"
      >
        <template slot-scope="scope">
          {{ scope.row.nodeGpuMemStr || '-' }}
        </template>
      </el-table-column>
      <el-table-column prop="createTimeStr" label="创建时间" width="170" />
      <el-table-column label="操作" width="140" fixed="right">
        <template slot-scope="scope">
          <el-button
            type="primary"
            size="mini"
            style="height: 22px; line-height: 22px; padding: 0 10px"
            @click="editClick(scope.row)"
          >编辑</el-button>
          <el-button
            type="danger"
            style="height: 22px; line-height: 22px; padding: 0 10px"
            size="mini"
            :disabled="scope.row.nodeRole == 'master'"
            @click="deleteClick(scope.$index)"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-row type="flex" justify="end" style="margin-top: 25px">
      <el-pagination
        background
        layout="total, sizes, prev, pager, next"
        :page-sizes="[10, 15, 20]"
        :page-size="pageSize"
        :current-page.sync="pageNum"
        :total="totalNum"
        @current-change="changePage"
        @size-change="sizeChange"
      />
    </el-row>

    <!-- 编辑 -->
    <el-dialog
      class="node-mgmt-dialog"
      title="编辑节点"
      :visible="showEditDialog"
      width="700px"
      top="10vh"
      :close-on-click-modal="false"
      @close="showEditDialog = false"
    >
      <el-form
        ref="editForm"
        size="small"
        :rules="editRules"
        :model="editForm"
        label-width="auto"
      >
        <el-form-item label="节点名称" prop="nodeName">
          <el-input
            v-model="editForm.nodeName"
            :disabled="true"
            placeholder="请输入节点名称"
          />
        </el-form-item>
        <!-- <el-form-item class="formItem left" label="节点类型" prop="nodeType">
          <el-select
            v-model="editForm.nodeType"
            placeholder="请选择节点类型"
            style="width: 100%"
            :disabled="true"
          >
            <el-option
              v-for="item in nodeTypeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item> -->
        <el-form-item class="formItem" label="角色" prop="nodeRole">
          <el-input
            v-model="editForm.nodeRole"
            placeholder="请选择角色"
            :disabled="true"
          />
        </el-form-item>
        <el-form-item class="formItem left" label="云商" prop="cloudProvider">
          <el-select
            v-model="editForm.cloudProvider"
            placeholder="请选择云商"
            style="width: 100%"
            :disabled="true"
          >
            <el-option
              v-for="item in cloudVendors"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <!-- <el-form-item class="formItem" label="主机" prop="vmName">
          <el-input
            v-model="editForm.vmName"
            placeholder="请选择主机"
            :disabled="true"
          />
        </el-form-item> -->
        <!-- <el-form-item label="部署位置" prop="location">
          <el-input
            v-model="editForm.location"
            placeholder="请输入部署位置"
            :disabled="true"
          />
        </el-form-item> -->
        <el-form-item label="标签" prop="nodeLabelMap">
          <div class="nodeLabelMap">
            <el-row
              v-for="(item, index) in editForm.nodeLabelMap"
              :key="index"
              style="margin-bottom: 10px"
              type="flex"
              align="middle"
            >
              <span>键</span>
              <el-input
                v-model="editForm.nodeLabelMap[index].key"
                :disabled="!editForm.nodeLabelMap[index].isLocal"
                style="width: 230px; margin: 0 20px 0 10px"
              />
              <span>值</span>
              <el-input
                v-model="editForm.nodeLabelMap[index].value"
                :disabled="!editForm.nodeLabelMap[index].isLocal"
                style="width: 230px; margin: 0 20px 0 10px"
              />
              <i
                v-if="editForm.nodeLabelMap[index].isLocal"
                style="font-size: 20px"
                class="el-icon-delete grey"
                @click="deleteNodeLabel(index)"
              ></i>
            </el-row>
            <i
              style="font-size: 28px; line-height: 40px"
              class="el-icon-circle-plus-outline"
              @click="addNodeLabel"
            ></i>
          </div>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button
          size="small"
          @click="showEditDialog = false"
        >取 消</el-button>
        <el-button
          type="primary"
          size="small"
          :loading="editConfirmLoading"
          @click="editConfirmClick"
        >确 定</el-button>
      </div>
    </el-dialog>

    <!-- 删除 -->
    <el-dialog
      class="node-mgmt-delete-dialog"
      title="删除节点"
      :visible="showDeleteDialog"
      width="700px"
      top="15vh"
      :close-on-click-modal="false"
      @close="showDeleteDialog = false"
    >
      <div class="error-wrapper">
        <img
          class="img"
          src="@/assets/imgs/intelligent-scheduling/img_error.png"
          alt=""
        />
        <div class="hint">若删除当前节点则当前业务也会全部停止并删除!</div>
      </div>
      <div slot="footer" class="dialog-footer">
        <el-button
          size="small"
          @click="showDeleteDialog = false"
        >取 消</el-button>
        <el-button
          type="primary"
          size="small"
          :loading="deleteConfirmLoading"
          @click="deleteConfirmClick"
        >确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  getK8sClusterNodeInfos,
  editK8sClusterNodeInfo,
  deleteK8sClusterNodeInfo
} from '@/api/cnap/hybrid-cloud'
import commonTab from '../mixin/commonTab'
import cloudVendorHandle from '@/views/mixin/cloudVendorHandle.js'

export default {
  name: 'NodeMgmt',
  components: {},
  mixins: [commonTab, cloudVendorHandle],
  data() {
    /**
     * @description: nodeLabelMap校验
     * @param {*} rule
     * @param {*} value
     * @param {*} callback
     * @return {*}
     */
    var validateNodeLabelMap = (rule, value, callback) => {
      if (
        Array.isArray(this.editForm.nodeLabelMap) &&
        this.editForm.nodeLabelMap.length > 0
      ) {
        // nodeLabelMap不为空
        const reg = /^([a-zA-Z\d-_\\\/\:\.\s])*$/ // 校验的正则
        let hasIllegal = false // 是否存在不合法
        for (const item of this.editForm.nodeLabelMap) {
          if (
            item.isLocal && // 本地添加数据
            (item.key === '' ||
              !reg.test(item.key) ||
              item.value === '' ||
              !reg.test(item.value)) // 数据为空或不符合规则
          ) {
            // 存在不合法
            hasIllegal = true
            break
          }
        }
        if (hasIllegal) {
          callback(new Error('存在不合法的标签键值')) // 抛出异常
        } else {
          callback()
        }
      } else {
        callback(new Error('标签不能为空')) // 抛出异常
      }
    }
    return {
      showEditDialog: false, // 是否显示编辑弹窗
      nodeTypeOptions: [
        // 节点类型
        {
          label: '虚机',
          value: '虚机'
        },
        {
          label: '物理机',
          value: '物理机'
        }
      ],
      // 校验规则
      editRules: {
        // 节点类型
        nodeType: [
          { required: true, message: '请选择节点类型', trigger: 'blur' }
        ],
        // 角色
        nodeRole: [{ required: true, message: '请选择角色', trigger: 'blur' }],
        // 云商
        cloudProvider: [
          { required: true, message: '请选择云商', trigger: 'blur' }
        ],
        // 主机名称
        vmName: [{ required: true, message: '请选择主机', trigger: 'blur' }],
        // 位置
        location: [
          { required: true, message: '请输入部署位置', trigger: 'blur' }
        ],
        // 标签
        nodeLabelMap: [{ required: true, validator: validateNodeLabelMap }]
      },
      editForm: {}, // 编辑的form
      editConfirmLoading: false, // 编辑-确定按钮loading
      deleteDialogIndex: 0, // 删除条目的index
      deleteConfirmLoading: false, // 删除-确定按钮loading
      showDeleteDialog: false // 是否展示删除弹窗
    }
  },
  methods: {
    /**
     * @description: 编辑确定
     * @return {*}
     */
    editConfirmClick() {
      // 校验
      this.$refs.editForm.validate((valid, obj) => {
        if (valid) {
          this.editConfirmLoading = true
          // 格式转换 转换为object
          this.editForm.nodeLabelMap = this.editForm.nodeLabelMap.reduce(
            (prev, cur) => {
              prev[cur.key] = cur.value
              return prev
            },
            {}
          )
          // 编辑
          editK8sClusterNodeInfo({
            k8sClusterIp: this.editForm.k8sClusterIp,
            nodeName: this.editForm.nodeName,
            nodeLabelMap: this.editForm.nodeLabelMap
          })
            .then((res) => {
              this.$message.success({
                message: '编辑节点成功！',
                duration: '1500'
              })
              this.showEditDialog = false // 取消弹窗
              this.getNodeInfos() // 刷新数据
            })
            .finally(() => {
              this.editConfirmLoading = false
            })
        }
      })
    },
    /**
     * @description: 编辑节点弹窗-添加标签
     * @return {*}
     */
    addNodeLabel() {
      // 添加空数据占位
      this.editForm.nodeLabelMap.push({
        key: '',
        value: '',
        isLocal: true // 本地添加
      })
    },
    /**
     * @description: 编辑节点弹窗-删除标签
     * @param {*} index
     * @return {*}
     */
    deleteNodeLabel(index) {
      this.editForm.nodeLabelMap.splice(index, 1)
    },
    /**
     * @description: 编辑
     * @param {*} row
     * @return {*}
     */
    editClick(row) {
      const rowJson = JSON.parse(JSON.stringify(row)) // JSON解析
      const nodeLabels = []
      if (Object.keys(rowJson.nodeLabelMap).length > 0) {
        // 格式转换 转为数组
        Object.keys(rowJson.nodeLabelMap).forEach((key) => {
          nodeLabels.push({
            key: key,
            value: rowJson.nodeLabelMap[key],
            isLocal: false // 是否是本地添加的标签
          })
        })
      }
      this.editForm = rowJson
      this.editForm.nodeLabelMap = nodeLabels
      this.editForm.cloudProvider = this.formatVendorAccount(
        this.editForm.cloudVendor,
        this.editForm.accountName
      )
      this.showEditDialog = true
      if (this.$refs.editForm) {
        this.$refs.editForm.clearValidate() // 重置表单
      }
    },
    /**
     * @description: 删除确定
     * @return {*}
     */
    deleteConfirmClick() {
      this.deleteConfirmLoading = true
      const row = this.list[this.deleteDialogIndex]
      // 请求
      deleteK8sClusterNodeInfo({
        k8sClusterIp: row.k8sClusterIp,
        nodeName: row.nodeName
      })
        .then((res) => {
          this.$message.success('删除成功')
          this.showDeleteDialog = false
          if (this.list.length === 1) {
            // 当前页只有一条数据时 删除完刷新上一页数据
            this.pageNum = Math.max(this.pageNum - 1, 1)
          }
          this.getNodeInfos() // 刷新数据
        })
        .finally(() => {
          this.deleteConfirmLoading = false
        })
    },
    /**
     * @description: 删除
     * @param {*} scope
     * @return {*}
     */
    deleteClick(index) {
      this.deleteDialogIndex = index
      this.showDeleteDialog = true
    },
    /**
     * @description: size变化
     * @param {*} size
     * @return {*}
     */
    sizeChange(size) {
      this.pageSize = size
      this.pageNum = 1
      this.getNodeInfos() // 刷新数据
    },
    /**
     * @description: 页码变化
     * @param {*} pageNum
     * @return {*}
     */
    changePage(pageNum) {
      this.pageNum = pageNum
      this.getNodeInfos() // 刷新数据
    },
    /**
     * @description: 清除关键字
     * @return {*}
     */
    clearClick() {
      this.searchKey = ''
      this.pageNum = 1
      this.getNodeInfos() // 刷新数据
    },
    /**
     * @description: 查询
     * @return {*}
     */
    queryClick() {
      this.pageNum = 1
      this.getNodeInfos() // 刷新数据
    },
    /**
     * @description: 获取节点列表
     * @return {*}
     */
    getNodeInfos() {
      // 请求
      getK8sClusterNodeInfos({
        ...this.clusterParams,
        keyword: this.searchKey,
        pageNo: this.pageNum,
        pageSize: this.pageSize
      })
        .then((res) => {
          if (res.data) {
            this.totalNum = res.data.totalNum
            this.list = Array.isArray(res.data.result) ? res.data.result : []
          } else {
            // 数据为空处理
            this.totalNum = 0
            this.list = []
          }
        })
        .finally(() => {
          this.loading = false
        })
    },
    /**
     * @description: 初始化
     * @return {*}
     */
    initTabData() {
      this.searchKey = this.$route.query.keyword || '' // 获取路径参数
      this.loading = true
      this.pageNum = 1
      this.getNodeInfos()
    }
  }
}
</script>

<style lang="less" scoped>
@import "@/assets/css/common.less";
.node-mgmt-ctn {
  .node-table {
    /deep/ .el-table::before {
      background-color: #e9e9e9;
    }
    /deep/ .listHeaderCell {
      height: 40px;
      padding: 0;
      box-sizing: border-box;
      &:first-child {
        padding-left: 20px;
      }
    }
    /deep/ .el-table__body {
      .el-table__row td {
        height: 40px;
        padding: 0;
        &:first-child {
          padding-left: 20px;
        }
      }
    }
  }
  .formItem {
    display: inline-block;
    width: calc(50% - 20px);
    &.left {
      margin-right: 40px;
    }
  }
}
.node-mgmt-delete-dialog {
  .error-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 0 40px;

    .img {
      width: 65px;
    }
    .hint {
      margin-top: 10px;
      .textStyle(14px , 400, #4a4a4a);
      line-height: 20px;
    }
  }
}
</style>
